package guda.stark.biz.impl;

import java.util.*;

import com.alibaba.fastjson.JSON;
import guda.grape.util.Convert;
import guda.stark.biz.beans.vo.TreeNodeStateVO;
import guda.stark.biz.beans.vo.TreeNodeVO;
import guda.stark.biz.form.RoleResourceRelForm;
import guda.stark.biz.query.RoleResourceQuery;
import guda.stark.biz.util.Transform;
import guda.stark.biz.util.TransformHelper;
import guda.stark.dal.dao.ResourceDAO;
import guda.stark.dal.dao.RoleResourceRelDAO;
import guda.stark.dal.dataobject.ResourceDO;
import guda.stark.dal.dataobject.RoleResourceRelDO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import guda.stark.biz.RoleBiz;
import guda.stark.dal.dao.RoleDAO;
import guda.stark.dal.dataobject.RoleDO;
import guda.grape.autogen.common.page.BaseQuery;
import guda.grape.autogen.common.page.BizResult;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

public class RoleBizImpl implements RoleBiz{

    private final static Logger logger = LoggerFactory.getLogger(RoleBizImpl.class);

    @Autowired
    private RoleDAO roleDAO;
    @Autowired
    private ResourceDAO resourceDAO;
    @Autowired
    private RoleResourceRelDAO roleResourceRelDAO;
    @Autowired
    private TransactionTemplate transactionTemplate;

    public BizResult detail(long id) {
        BizResult bizResult = new BizResult();
        try{
            RoleDO roleDO = roleDAO.getRoleById(id);
            bizResult.data.put("roleDO", roleDO);
            bizResult.success = true;
        }catch(Exception e){
            logger.error("query Role error",e);
        }
        return bizResult;
}

    public BizResult list(BaseQuery baseQuery) {
        BizResult bizResult = new BizResult();
        try {
            int totalCount = roleDAO.countForPage(baseQuery);
            baseQuery.setTotalCount(totalCount);
            List<RoleDO> roleList = roleDAO.selectForPage(baseQuery);
            bizResult.data.put("roleList", roleList);
            bizResult.data.put("query", baseQuery);
            bizResult.success = true;
        } catch (Exception e) {
            logger.error("view Role list error", e);
        }
            return bizResult;
     }

    public BizResult delete(long id) {
        BizResult bizResult = new BizResult();
        try {
            roleDAO.delRoleById(id);
            bizResult.success = true;
        } catch (Exception e) {
            logger.error("delete role error", e);
        }
        return bizResult;
    }

    public BizResult create(RoleDO roleDO) {
        BizResult bizResult = new BizResult();
        try {
            long id = roleDAO.insert(roleDO);
            bizResult.data.put("id", id);
            bizResult.success = true;
        } catch (Exception e) {
            logger.error("create Role error", e);
        }
        return bizResult;
    }

    @Override
    public BizResult update(RoleDO roleDO) {
        BizResult bizResult = new BizResult();
        try {
            roleDAO.updateByIdSelective(roleDO);
            bizResult.success = true;
        } catch (Exception e) {
            logger.error("update Role error", e);
        }
        return bizResult;
    }

    @Override
    public BizResult loadAllResource(Long roleId) {
        BizResult bizResult = new BizResult();
        RoleResourceQuery roleResourceQuery = new RoleResourceQuery();
        roleResourceQuery.setRoleId(roleId);
        roleResourceQuery.setPageSize(300);
        List<RoleResourceRelDO> roleResourceRelDOs = roleResourceRelDAO.selectForPage(roleResourceQuery);
        Set<Long> resourceIdSet = TransformHelper.transform2Set(roleResourceRelDOs, new Transform<RoleResourceRelDO, Long>() {
            @Override
            public Long transform(RoleResourceRelDO object) {
                return object.getResourceId();
            }
        });

        BaseQuery baseQuery  = new BaseQuery();
        baseQuery.setPageSize(300);
        List<ResourceDO> resourceDOs = resourceDAO.selectForPage(baseQuery);
        Map<String,List<ResourceDO>> map = new HashMap<String, List<ResourceDO>>();
        for(ResourceDO resourceDO:resourceDOs){
            List<ResourceDO> resourceDOs1 = map.get(resourceDO.getResourceCat());
            if(resourceDOs1 == null){
                resourceDOs1 = new ArrayList<ResourceDO>();
                resourceDOs1.add(resourceDO);
                map.put(resourceDO.getResourceCat(),resourceDOs1);
            }else{
                resourceDOs1.add(resourceDO);
            }
        }
        Iterator<Map.Entry<String, List<ResourceDO>>> iterator = map.entrySet().iterator();
        TreeNodeVO root = new TreeNodeVO();
        root.setText("根目录");
        root.setId("0");
        root.setState(new TreeNodeStateVO(true, false));
        List<TreeNodeVO> list = new ArrayList<TreeNodeVO>();
        while(iterator.hasNext()){
            Map.Entry<String, List<ResourceDO>> next = iterator.next();
            TreeNodeVO child = new TreeNodeVO();
            child.setText(next.getKey());
            child.setId(next.getKey());
            child.setState(new TreeNodeStateVO(true, false));
            list.add(child);
            List<ResourceDO> value = next.getValue();
            List<TreeNodeVO> subChild = new ArrayList<TreeNodeVO>();
            child.setChildren(subChild);
            for(ResourceDO resourceDO:value){
                TreeNodeVO subChildNode = new TreeNodeVO();
                subChildNode.setText(resourceDO.getResourceName());
                subChildNode.setId(String.valueOf(resourceDO.getResourceId()));
                if(resourceIdSet.contains(resourceDO.getResourceId())) {
                    subChildNode.setState(new TreeNodeStateVO(true, true));
                }else{
                    subChildNode.setState(new TreeNodeStateVO(true, false));
                }
                subChild.add(subChildNode);
            }
        }
        root.setChildren(list);
        bizResult.data.put("resourceTree", JSON.toJSONString(root));
        bizResult.success = true;
        return bizResult;
    }

    @Override
    public BizResult bindResource(final RoleResourceRelForm roleResourceRelForm) {
        BizResult bizResult = new BizResult();
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                for(String resourceId:roleResourceRelForm.getResourceId()){
                    long resourceIdLong = Convert.toLong(resourceId);
                    if(resourceIdLong == 0){
                        continue;
                    }
                    RoleResourceRelDO roleResourceRel = roleResourceRelDAO.getRoleResourceRel(roleResourceRelForm.getRoleId(),resourceIdLong );
                    if(roleResourceRel == null){
                        RoleResourceRelDO roleResourceRelDO = new RoleResourceRelDO();
                        roleResourceRelDO.setResourceId(resourceIdLong);
                        roleResourceRelDO.setRoleId(roleResourceRelForm.getRoleId());
                        roleResourceRelDAO.insert(roleResourceRelDO);
                    }
                }
            }
        });

        bizResult.success = true;
        return bizResult;
    }


}
